package com.ctshk.rpc.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.cms.constant.CmsConstant;
import com.ctshk.rpc.cms.dto.BannerDTO;
import com.ctshk.rpc.cms.dto.ContentDTO;
import com.ctshk.rpc.cms.dto.LinkTypeDTO;
import com.ctshk.rpc.cms.entity.Banner;
import com.ctshk.rpc.cms.entity.BannerPosition;
import com.ctshk.rpc.cms.entity.LinkType;
import com.ctshk.rpc.cms.mapper.BannerMapper;
import com.ctshk.rpc.cms.mapper.BannerPositionMapper;
import com.ctshk.rpc.cms.mapper.LinkTypeMapper;
import com.ctshk.rpc.cms.req.*;
import com.ctshk.rpc.cms.service.IBannerService;
import com.ctshk.rpc.goods.dto.CMSCommodityDTO;
import com.ctshk.rpc.goods.service.ICMSCommodityService;
import com.ctshk.rpc.localfun.dto.LocalFunResourceDTO;
import com.ctshk.rpc.localfun.req.LocalFunResourceReq;
import com.ctshk.rpc.localfun.service.ILocalFunResourceService;
import com.ctshk.rpc.scenic.dto.ScenicProductListDTO;
import com.ctshk.rpc.scenic.req.ScenicProductListReq;
import com.ctshk.rpc.scenic.service.IScenicProductService;
import com.ctshk.rpc.season.dto.FixedSeasonProductPageDTO;
import com.ctshk.rpc.season.service.ISeasonFixedProductService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.tour.service.ISeriesTripService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * banner图管理 服务实现类
 * </p>
 *
 * @author LiZhiming
 * @since 2021-04-23
 */
@DubboService
public class BannerServiceImpl extends ServiceImpl<BannerMapper, Banner> implements IBannerService {

    @Autowired
    private LinkTypeMapper linkTypeMapper;

    @Autowired
    private BannerPositionMapper bannerPositionMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ContentServiceImpl contentService;

    @DubboReference
    private ISysUserService sysUserService;

    @DubboReference
    private ISeasonFixedProductService seasonFixedProductService;

    @DubboReference
    private ILocalFunResourceService localFunResourceService;

    @DubboReference
    private IScenicProductService scenicProductService;

//    @DubboReference
//    private ISeriesTripScheduleService seriesTripScheduleService;

    @DubboReference
    private ISeriesTripService seriesTripService;

    @DubboReference
    private ICMSCommodityService icmsCommodityService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result insert(BannerAddReq req, TokenUser tu) {
        Banner banner = EntityUtil.copy(req, Banner.class);
        LocalDateTime now = LocalDateTime.now();
        Long id = IdWorker.getId();
        if (req.getLinkTypeReq() != null && req.getLinkTypeReq().getLinkType() != null) {
            LinkType copy = EntityUtil.copy(req.getLinkTypeReq(), LinkType.class);
            copy.setId(IdWorker.getId());
            copy.setCorrelationId(id);
            copy.setCreateId(tu.getId());
            copy.setGmtCreate(now);
            copy.setIsDeleted(IsDeletedCode.NO.getCode());
            int insert = linkTypeMapper.insert(copy);
            if(insert < 1){
                throw new BusinessException(SystemError.CMS_23007);
            }
        }else{
            throw new BusinessException(SystemError.CMS_23006);
        }
        banner.setCreateId(tu.getId());
        banner.setGmtCreate(now);
        banner.setSort(req.getSort() == null ? 100 : req.getSort());
        banner.setId(id);
        banner.setIsDeleted(IsDeletedCode.NO.getCode());
        int insert = baseMapper.insert(banner);
        //新增成功banner后再新增链接类型
        if (insert > 0) {
            //做了修改操作如果存在这个bannaer位的缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_BANNER_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(id);
        }
        return Result.failed(SystemError.CMS_23000);
    }

    @Override
    public Result<BannerDTO> queryById(String bannerId) {
        BannerDTO b = null;
        QueryWrapper<Banner> qw = new QueryWrapper<>();
        qw.lambda().eq(Banner::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Banner::getId, bannerId);
        Banner banner = baseMapper.selectOne(qw);
        if (banner != null) {
            b = EntityUtil.copy(banner, BannerDTO.class);
            QueryWrapper<LinkType> qwlt = new QueryWrapper<>();
            qwlt.lambda().eq(LinkType::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(LinkType::getCorrelationId, bannerId);
            LinkTypeDTO lt = EntityUtil.copy(linkTypeMapper.selectOne(qwlt), LinkTypeDTO.class);
            b.setLinkTypeDto(lt);
            //調用接口填充產品信息
            setProduct(lt);
        }
        return Result.success(b);
    }

    @Override
    public PageResponse<BannerDTO> queryList(BannerQueryReq req) {
        Page<Banner> page = new Page(req.getPageNo(), req.getPageSize());
        QueryWrapper<Banner> qw = new QueryWrapper();
        qw.lambda().eq(Banner::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(req.getBannerName() != null, Banner::getBannerName, req.getBannerName())
                .eq(req.getTitle() != null, Banner::getTitle, req.getTitle())
                .eq(req.getBannerPositionId() != null, Banner::getBannerPositionId, req.getBannerPositionId())
                .orderByAsc(Banner::getSort, Banner::getGmtCreate);
        Page<Banner> bannerPage = baseMapper.selectPage(page, qw);
        List<BannerDTO> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(bannerPage.getRecords())) {
            for (Banner banner : bannerPage.getRecords()) {
                QueryWrapper<LinkType> qwlt = new QueryWrapper<>();
                qwlt.lambda().eq(LinkType::getIsDeleted, IsDeletedCode.NO.getCode())
                        .eq(LinkType::getCorrelationId, banner.getId());
                LinkType linkType = linkTypeMapper.selectOne(qwlt);
                BannerDTO copy = EntityUtil.copy(banner, BannerDTO.class);
                UserDTO userDTO = sysUserService.loadUserInfo(banner.getCreateId(), 1);
                if (userDTO != null) {
                    copy.setUserName(userDTO.getCnSurname() + userDTO.getCnName());
                }
                LinkTypeDTO lt = EntityUtil.copy(linkType, LinkTypeDTO.class);
                copy.setLinkTypeDto(lt);
                list.add(copy);
                //調用接口填充產品信息
//                setProduct(lt);
            }
            return new PageResponse<>(list,
                    page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() *
                    page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
        }
        return new PageResponse<>(null,
                page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() *
                page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
    }

    @Override
    public List<BannerDTO> queryListByCode(BannerPositionByTypeReq req) {
        ValueOperations ops = redisTemplate.opsForValue();
        List<BannerDTO> list = new ArrayList<>();
        BannerPosition bp = bannerPositionMapper.selectOne(
                Wrappers.<BannerPosition>lambdaQuery().eq(BannerPosition::getBannerCode, req.getCode())
                        .eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode())
        );
        if (bp == null) {
            return null;
        }
        //先取缓存不存在就重新查
        String opsBpl = (String) ops.get(CmsConstant.CMS_BANNER_REDIS_KEY + bp.getId().toString() + (req.getLinkType() == null ? "" : req.getLinkType()));
        if (StringUtils.isNotBlank(opsBpl)) {
            JSONArray ja = JSON.parseArray(opsBpl);
            List<BannerDTO> lista = ja.toJavaList(BannerDTO.class);
            return lista;
        }
        QueryWrapper<Banner> qw = new QueryWrapper();
        qw.lambda().eq(Banner::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Banner::getBannerPositionId, bp.getId())
                .orderByAsc(Banner::getSort, Banner::getGmtCreate);
        List<Banner> banners = baseMapper.selectList(qw);
        if (CollectionUtils.isNotEmpty(banners)) {
            for (Banner banner : banners) {
                QueryWrapper<LinkType> qwlt = new QueryWrapper<>();
                qwlt.lambda().eq(LinkType::getIsDeleted, IsDeletedCode.NO.getCode())
                        .eq(LinkType::getCorrelationId, banner.getId());
                LinkType linkType = linkTypeMapper.selectOne(qwlt);
                if (linkType != null) {
                    BannerDTO copy = EntityUtil.copy(banner, BannerDTO.class);
                    LinkTypeDTO lt = EntityUtil.copy(linkType, LinkTypeDTO.class);
                    copy.setLinkTypeDto(lt);
                    list.add(copy);
                    //調用接口填充產品信息
//                    setProduct(lt);
                }
            }
        }

        if (req.getLinkType() != null) {
            if (CollectionUtils.isNotEmpty(list)) {
                List<BannerDTO> collect = list.stream().filter(e ->
                        e.getLinkTypeDto().getLinkType() == req.getLinkType()
                ).collect(Collectors.toList());
                if (list != null && list.size() > 0) {
                    ops.set(bp.getId() + "" + req.getLinkType(), JSON.toJSONString(list));
                }
                return collect;
            }
        }
        if (list != null && list.size() > 0) {
            ops.set(CmsConstant.CMS_BANNER_REDIS_KEY + bp.getId().toString() + (req.getLinkType() == null ? "" : req.getLinkType()), JSON.toJSONString(list));
        }
        return list;
    }

    private void setProduct(LinkTypeDTO lt) {
        if (lt == null) return;
        //調用接口填充產品信息
        if (lt.getProductId() != null && lt.getLinkType() != null) {
            List<Long> ids = new ArrayList<>();
            ids.add(lt.getProductId());
            switch (lt.getLinkType()) {
                case 3://文檔
                    Result<ContentDTO> contentDTOResult = contentService.queryById(lt.getProductId().toString());
                    if (contentDTOResult.getData() != null) {
                        lt.setProduct(contentDTOResult.getData());
                    }
                    break;
                case 4://旅行团
                    lt.setProduct(seriesTripService.basicInformation(lt.getProductId()));
                    break;
                case 5://套票
                    List<FixedSeasonProductPageDTO> seasonProductList = seasonFixedProductService.getSeasonProductList(lt.getProductId().toString());
                    if (seasonProductList != null && seasonProductList.size() > 0) {
                        lt.setProduct(seasonProductList.get(0));
                    }
                    break;
                case 6://酒店
                    break;
                case 7://门票
                    ScenicProductListReq splr = new ScenicProductListReq();
                    splr.setIds(ids);
                    List<ScenicProductListDTO> data = scenicProductService.getListByIds(splr).getData();
                    if (data != null && data.size() > 0) {
                        lt.setProduct(data.get(0));
                    }
                    break;
                case 8://当地玩乐
                    LocalFunResourceReq lfrr = new LocalFunResourceReq();
                    lfrr.setProductIds(ids);
                    List<LocalFunResourceDTO> localFunResourceDTOS = localFunResourceService.queryListByProductIds2(lfrr);
                    if (localFunResourceDTOS != null && localFunResourceDTOS.size() > 0) {
                        lt.setProduct(localFunResourceDTOS.get(0));
                    }
                    break;
                case 9://商品
                    List<CMSCommodityDTO> cmsCommodityDTOS = icmsCommodityService.selectCMSCommodityDTOByIds(ids);
                    if (cmsCommodityDTOS != null && cmsCommodityDTOS.size() > 0) {
                        lt.setProduct(cmsCommodityDTOS.get(0));
                    }
                    break;
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(BannerUpdateReq req, TokenUser tu) {
        LocalDateTime now = LocalDateTime.now();
        Banner copy = EntityUtil.copy(req, Banner.class);
        copy.setModifiedId(tu.getId());
        copy.setGmtModified(now);
        int i = baseMapper.updateById(copy);
        if (i > 0) {
            //如果没有连接类型就不修改
            if(req.getLinkTypeDto() != null){
                //根据correlationId修改（bannerID）
                LinkType copy1 = EntityUtil.copy(req.getLinkTypeDto(), LinkType.class);
                copy1.setModifiedId(tu.getId());
                copy1.setGmtModified(now);
                QueryWrapper<LinkType> qw = new QueryWrapper<>();
                qw.lambda().eq(LinkType::getCorrelationId, req.getId())
                        .eq(LinkType::getIsDeleted, IsDeletedCode.NO.getCode());
                LinkType linkType = linkTypeMapper.selectOne(qw);
                //如果在修改时发现这个banner没有一一对应的连接类型就新增一个补上
                if(linkType == null){
                    copy1.setId(SnowflakeIdWorker.nextId());
                    copy1.setCorrelationId(copy.getId());
                    copy1.setCreateId(tu.getId());
                    copy1.setGmtCreate(now);
                    copy1.setIsDeleted(IsDeletedCode.NO.getCode());
                    linkTypeMapper.insert(copy1);
                }else{
                    linkTypeMapper.update(copy1, qw);
                }
            }
            //做了修改操作如果存在这个bannaer位的缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_BANNER_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(req.getId());
        }
        return Result.failed(SystemError.CMS_23002);
    }

    @Override
    public Result updateStatusById(UpdateStatusReq req) {
        int i = baseMapper.updateStatusById(req.getId(), req.getStatus());
        if (i > 0) {
            Banner banner = baseMapper.selectById(req.getId());
            if (banner != null) {
                //做了修改操作如果存在这个bannaer位的缓存就清除缓存
                Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_BANNER_REDIS_KEY));
                if (CollUtil.isNotEmpty(keysRecommend)) {
                    redisTemplate.delete(keysRecommend);
                }
            }
        }
        return Result.success(i);
    }
}
